﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using KLS.PPDS.Utility;
using NHibernate;
using NHibernate.Cfg;


namespace KLS.PPDS.Data.Database.Common
{
    public sealed class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;
        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }

        // Session key.
        const string CurrentSessionKey = "nhibernate.current_session";
        // Transaction key.
        const string TransactionKey = "nhibernate.current_transaction";
        // NHibernate session container.
        static readonly ISessionFactory SessionFactory = new Configuration().Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, WebConfig.NhibernateConfigFile)).AddAssembly(typeof(NHibernateHelper).Assembly).BuildSessionFactory();


        public static void BeginSession()
        {
            GetCurrentSession();
        }

        public static ISession GetCurrentSession()
        {
            HttpContext context = HttpContext.Current;
            ISession currentSession = null;

            if (context == null)
            {
                currentSession = SessionFactory.OpenSession();
                return currentSession;
            }


            // if (context!=null && context.Items[CurrentSessionKey] != null) 
            {
                currentSession = context.Items[CurrentSessionKey] as ISession;
            }

            if (currentSession != null && !currentSession.IsOpen)
            {
                currentSession = SessionFactory.OpenSession();
            }
            else if (currentSession == null)
            {
                currentSession = SessionFactory.OpenSession();
                //  if (context != null) 
                {
                    context.Items[CurrentSessionKey] = currentSession;
                }
            }
            return currentSession;
        }

        // Close the opened session of session factory by this function.
        public static void CloseSession()
        {
            HttpContext context = HttpContext.Current;
            var currentSession = context.Items[CurrentSessionKey] as ISession;
            if (currentSession == null)
            {
                // No current session
                return;
            }
            if (currentSession.IsOpen)
            {
                currentSession.Close();
            }
            context.Items.Remove(CurrentSessionKey);
        }

        // Close the Created session factory by this function.
        public static void CloseSessionFactory()
        {
            if (SessionFactory != null)
            {
                SessionFactory.Close();
            }
        }

        public static void BeginTransaction()
        {
            var transaction = ContextTransaction;
            if (transaction == null)
            {
                transaction = GetCurrentSession().BeginTransaction();
                ContextTransaction = transaction;
            }
        }

        public static void CommitTransaction()
        {
            var transaction = ContextTransaction;
            try
            {
                if (HasOpenTransaction())
                {
                    GetCurrentSession().Flush();
                    transaction.Commit();
                    ContextTransaction = null;
                }
            }
            catch (HibernateException oEx)
            {
                //"System is rollbacking for the reason:" +oEx.Message
                RollbackTransaction();
                throw;
            }
        }

        public static bool HasOpenTransaction()
        {
            ITransaction transaction = ContextTransaction;
            return transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack;
        }

        public static void RollbackTransaction()
        {
            try
            {
                ITransaction transaction = ContextTransaction;
                if (HasOpenTransaction())
                {
                    transaction.Rollback();
                }
                ContextTransaction = null;
            }
            finally
            {
                //"System is closing the session after rollbacking:"
                CloseSession();
            }
        }

        private static ITransaction ContextTransaction
        {
            get
            {
                if (IsInWebContext())
                {
                    return (ITransaction)HttpContext.Current.Items[TransactionKey];
                }
                else
                {
                    return (ITransaction)System.Runtime.Remoting.Messaging.CallContext.GetData(TransactionKey);
                }
            }
            set
            {
                if (IsInWebContext())
                {
                    HttpContext.Current.Items[TransactionKey] = value;
                }
                else
                {
                    System.Runtime.Remoting.Messaging.CallContext.SetData(TransactionKey, value);
                }
            }
        }

        private static bool IsInWebContext()
        {
            return HttpContext.Current != null;
        }
    }
}
